package com.hhd.flow.engine.cmd.impl;

import com.hhd.flow.engine.utils.CommonUtils;
import com.hhd.flow.engine.utils.FlowUtils;
import com.hhd.flow.engine.vo.CommentType;
import com.hhd.flow.engine.vo.FlowModel;
import com.hhd.flow.engine.vo.FlowUser;
import com.hhd.flow.engine.vo.UserTask;
import com.hhd.flow.entity.*;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.SuperBuilder;
import org.apache.logging.log4j.util.Strings;

import java.util.LinkedHashSet;
import java.util.List;
import java.util.stream.Collectors;

@Setter
@Getter
@SuperBuilder(toBuilder = true)
public class AddNotifyCommand extends FlowUserTaskChangeCommand<Void> {
    private String comment;
    private List<FlowUser> flowUsers;
    private String flowUserTaskId;
    private String commentInfo;

    //下面的参数是运行时参数
    private FlowUser currentUser;
    private FlowUserTask flowUserTask;
    private FlowModel flowModel;
    private UserTask userTask;
    private FlowTask flowTask;
    private FlowProcessInstance flowProcessInstance;
    private FlowComment flowComment;
    private List<FlowUserTask> flowUserTasks;

    @Override
    public Void execute() {
        prepare();

        createUserTask();

        createComment();

        publishNotifyEvent();
        return null;
    }

    protected void publishNotifyEvent() {

        afterChangeFlowUserTask(flowProcessInstance); //触发创建用户任务的事件
    }

    private void createComment() {
        flowComment = FlowUtils.createComment(flowUserTask, comment, null, null, CommentType.addNotify, commentInfo);
        getEngine().getFlowCommentService().save(flowComment);
    }

    private void createUserTask() {
        flowUserTasks = flowUsers.stream()
                .map(this::createNotifyFlowUserTask)
                .peek(this::publishCreateFlowUserTask)
                .collect(Collectors.toList());
    }

    protected void publishCreateFlowUserTask(FlowUserTask flowUserTask) {
    }

    private FlowUserTask createNotifyFlowUserTask(FlowUser flowUser) {
        FlowUserTask notifyUserTask = checkDeplicate(flowUser);
        if(!CommonUtils.isEmpty(notifyUserTask)) return notifyUserTask;

        notifyUserTask = FlowUtils.createFlowUserTask(flowTask, flowUser, flowProcessInstance, userTask);
        notifyUserTask.setNotify(true);
        notifyUserTask.setNotifyFrom(currentUser.getId());
        notifyUserTask.setNotifyFromUsername(currentUser.getUsername());
        getEngine().getFlowUserTaskService().save(notifyUserTask);
        return notifyUserTask;
    }

    private void prepare() {
        if (CommonUtils.isEmpty(currentUser)) {
            currentUser = getEngine().getCurrentUser();
        }

        flowUserTask = getEngine().getFlowUserTaskService().getById(flowUserTaskId);
        CommonUtils.isEmptyThrow(flowUserTask, new RuntimeException("没有找到用户任务：" + flowUserTaskId));

        flowTask = getFlowTask();

        flowModel = loadFlowModelByProcessInstanceId(flowUserTask.getProcessInstanceId());
        userTask = flowModel.getUserTaskById(flowUserTask.getTaskDefinitionId());

        createVirtualProcessInstance();

        beforeChangeFlowUserTask(flowProcessInstance);
    }

    private FlowUserTask checkDeplicate(FlowUser flowUser) {
        List<FlowUserTask> list = getEngine().getFlowUserTaskService().lambdaQuery()
                .eq(FlowUserTask::getTaskDefinitionId, flowTask.getTaskDefinitionId())
                .eq(FlowUserTask::getProcessInstanceId, flowTask.getProcessInstanceId())
                .eq(FlowUserTask::getUserId, flowUser.getId())
                .list();
        if (CommonUtils.isEmpty(list)) return null;

        FlowUserTask notified = list.get(0);
        //当前用户已经被知会过了
        String notifyFrom = notified.getNotifyFrom();
        String notifyFromUsername = notified.getNotifyFromUsername();
        LinkedHashSet<String> ids = new LinkedHashSet<>();
        LinkedHashSet<String> names = new LinkedHashSet<>();
        if (!CommonUtils.isEmpty(notifyFrom)) {
            for (String s : notifyFrom.split(",")) {
                ids.add(s);
            }
        }
        ids.add(currentUser.getId());
        if (!CommonUtils.isEmpty(notifyFromUsername)) {
            for (String s : notifyFromUsername.split(",")) {
                names.add(s);
            }
        }
        names.add(currentUser.getUsername());

        notifyFrom = Strings.join(ids, ',');
        notifyFromUsername = Strings.join(names, ',');
        notified.setNotifyFrom(notifyFrom);
        notified.setNotifyFromUsername(notifyFromUsername);

        getEngine().getFlowUserTaskService().updateById(notified);
        return notified;
    }

    private FlowTask getFlowTask() {
        FlowTask flowTask1 = getEngine().getFlowTaskService().getById(flowUserTask.getTaskInstanceId());
        if (CommonUtils.isEmpty(flowTask1)) {
            FlowTaskHistory flowTaskHistory = getEngine().getFlowTaskHistoryService().getById(flowUserTask.getTaskInstanceId());
            CommonUtils.isEmptyThrow(flowTaskHistory, new RuntimeException("没有找到任务：" + flowUserTask.getTaskInstanceId()));
            return CommonUtils.copyTo(flowTaskHistory, FlowTask.class);
        }
        return flowTask1;
    }

    private void createVirtualProcessInstance() {
        flowProcessInstance = new FlowProcessInstance();
        flowProcessInstance.setFormTypeId(flowUserTask.getFormTypeId());
        flowProcessInstance.setFormId(flowUserTask.getFormId());
        flowProcessInstance.setProcessTitle(flowUserTask.getProcessTitle());
        flowProcessInstance.setApplyBy(flowUserTask.getApplyBy());
        flowProcessInstance.setApplyByName(flowUserTask.getApplyByName());
    }
}
